using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Reflection;
using System.Diagnostics;


namespace MVCFramework.Models.Controllers
{
    [Serializable ]
   public class IDController : Controller
    {
        private static readonly LoggerAdapter  log = new LoggerAdapter (typeof(IDController));

        [field: NonSerialized]
        private readonly BooleanSwitch IdSwitch = new BooleanSwitch("TraceIds", "Trace ids Switch");

        public void AdditionHandler(object sender, ModelModificationEventArgs Args)
        {
            if (sender != null && Args.Changetype == ModelChangeType.Added && Args.Modified != null)
            {
                if (Args.Modified is IModelData)
                    CheckAddition(Args.Modified as IModelData);
            }
        }
        public void RemovalHandler(object sender, ModelModificationEventArgs Args)
        {
            if (sender != null && Args.Changetype == ModelChangeType.Removed && Args.Modified != null)
            {
                if (Args.Modified is IModelData)
                    CheckRemoval(Args.Modified as IModelData);
            }
        }
        IdManager<ICountable> idManager;

        public IDController(IModel model, IdManager<ICountable> idManager)
            : base(model)
        {
            this.idManager = idManager;

        }

        bool ShowRegistration = true;

        public override bool CheckAddition(IModelData _object)
        {
            if (this.IsEnabled)
            {
                RegisterDeepContainedData(_object);
            }
            return false;
        }
        public override bool CheckRemoval(IModelData _object)
        {

            if (this.IsEnabled)
                UnRegisterDeepContainedData(_object);
            return false;
        }

        private void RegisterDeepContainedData(object _object)
        {
            if (_object is ICountable)
            { RegisterCountable(_object); return; }

            if (_object.GetType().IsDefined(typeof(CountableContainerAttribute), true))
            {
                object[] atrributes = _object.GetType().GetCustomAttributes(typeof(CountableContainerAttribute), true);
                string[] Properties = (atrributes[0] as CountableContainerAttribute).Properties;
                PropertyInfo property;
                foreach (string propertyname in Properties)
                {
                    property = _object.GetType().GetProperty(propertyname);

                    MethodInfo getinfo = property.GetGetMethod(true);
                    object[] aa = new object[0];
                    object _returnObject = getinfo.Invoke(_object, aa);
                    if (_returnObject is IList)
                    {
                        foreach (object data in (_returnObject as IList))
                        {
                            log.Info(" Deep id Cheching  and assignemwnt for " + data.ToString());

                            RegisterDeepContainedData(data);
                        }
                    }
                    //  else
                    //    RegisterDeepContainedData(_returnObject);

                }
            }
        }
        private void UnRegisterDeepContainedData(object _object)
        {
            if (_object is ICountable)
            { UnRegisterCountable(_object); return; }

            foreach (PropertyInfo property in _object.GetType().GetProperties())
            {
                if (property.IsDefined(typeof(CountableContainerAttribute), false))
                {
                    MethodInfo getinfo = property.GetGetMethod(true);
                    object[] aa = new object[0];
                    object _returnObject = getinfo.Invoke(_object, aa);
                    if (_returnObject is IList)
                    {
                        foreach (object data in (_returnObject as IList))
                        {
                            log.Info(" Deep id Cheching  and assignemwnt for " + data.ToString());
                            UnRegisterDeepContainedData(data);
                        }
                    }
                    // else
                    //   UnRegisterDeepContainedData(_returnObject);
                }
            }
        }

        private void RegisterCountable(object _object)
        {
            if (IdSwitch.Enabled)
            {
            
            }
              //  System.Diagnostics.Trace.TraceInformation("Registring object " + _object.ToString());
                log.Info("New Id :" + idManager.Register(_object as ICountable));

             //   if (IdSwitch.Enabled)
               //     System.Diagnostics.Debug.Assert(!(((ICountable)_object).Id <= 0), " ImodelDta " + _object.ToString() + " Shound have been Assigned an Id in order to be in the model");

            //    if (((ICountable)_object).Id == 0 && _object is IModelData)
                //    log.Warn("Object " + _object.ToString() + " was Not Assigned with an Id");

       
        }
        private void UnRegisterCountable(object _object)
        {
            if (IdSwitch.Enabled)
            {

           //     if (_object is ICountable & _object is IModelData)
            //        System.Diagnostics.Debug.Assert(((ICountable)_object).Id != 0, " ImodelDta " + _object.ToString() + " Shound have been Assigned an Id in order to be REMOVED form model");

             //   System.Diagnostics.Trace.TraceInformation("Registring object " + _object.ToString());
            //    log.Info("Registring " + _object);
            }
            idManager.Remove(_object as ICountable);
        }
    }
}
